# coding: utf-8

import socket
import uuid
import json

# 用于动态设备注册的服务器ip地址
REGISTRATION_SERVER = '192.168.1.7'


# 获取当前设备的MAC地址
def get_mac_address():
    mac = uuid.UUID(int=uuid.getnode()).hex[-12:]
    return ":".join([mac[e:e + 2] for e in range(0, 11, 2)])


# 获取当前设备的ip地址
def get_ip_address():
    tmp = None
    try:
        tmp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        tmp.connect(('8.8.8.8', 80))
        ip = tmp.getsockname()[0]
    finally:
        tmp.close()
    return ip


# 注册当前的设备，包括静态设备注册和动态设备注册，其结果是生成configure.json
def register():
    file_path = 'data/device.json'
    with open(file_path, 'r') as f:
        static_device_list = json.load(f)['static_device']
    mac = get_mac_address()
    if mac in static_device_list.keys():
        # static registration
        # 静态设备注册，注册最初始的三台设备，它们注册需要的信息被存放在device.json中
        ip_address = static_device_list[mac]
        static_device_list.pop(mac)
        peers_list = dict()
        for x in static_device_list.keys():
            peers_list[x.replace(':', '')] = (static_device_list[x], 10001)
        init_data = {
            'id': mac.replace(':', ''),
            'addr': (ip_address, 10001),
            'client_port': 10000,
            'peers': peers_list
        }
        print(init_data)
        configure_path = 'data/configure.json'
        with open(configure_path, 'w') as cf:
            json.dump(init_data, cf)
    else:
        # dynamic registration
        # 当设备不在静态注册设备列表中时，首次注册需要动态注册，将注册信息发给leader，由leader同步给所有follower
        # 所有设备更新configure.json和peers参数，最后由leader发送所有设备列表给recv。
        cs = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        ip_address = get_ip_address()
        addr = (REGISTRATION_SERVER, 10001)
        data = {
            'type': 'client_dynamic_register',
            'device_mac': mac.replace(':', ''),
            'device_ip': ip_address,
            'device_port': 10001
        }
        print('register send: ', data)
        data = json.dumps(data).encode('utf-8')
        cs.sendto(data, addr)
        recv_addr = (ip_address, 10002)
        ss: socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        ss.bind(recv_addr)
        # while True:
        recv_data, _ = ss.recvfrom(65535)
        recv_data = json.loads(recv_data)
        print('registration recv', recv_data)
        init_data = {
            'id': mac.replace(':', ''),
            'addr': (ip_address, 10001),
            'client_port': 10000,
            'peers': recv_data['device_list']
        }
        print(init_data)
        configure_path = 'data/configure.json'
        with open(configure_path, 'w') as cf:
            json.dump(init_data, cf)


if __name__ == '__main__':
    register()
